package com.zzyl.framework.interceptor;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.zzyl.common.core.domain.model.LoginUser;
import com.zzyl.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;

/**
 * MyBatis-Plus 自动填充处理器
 * 自动填充创建时间、更新时间、创建人、更新人等字段
 *
 * @author zzyl
 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * 默认用户ID（用于非Web环境或无法获取当前用户时）
     */
    private static final Long DEFAULT_USER_ID = 1L;

    /**
     * 排除自动填充createBy和updateBy的路径前缀
     */
    private static final String EXCLUDE_PATH_PREFIX = "/member/";

    /**
     * 插入时自动填充
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        try {
            Date now = new Date();
            
            // 时间字段始终自动填充（所有环境都需要）
            this.strictInsertFill(metaObject, "createTime", Date.class, now);
            this.strictInsertFill(metaObject, "updateTime", Date.class, now);
            
            // 用户字段根据环境和路径判断是否填充
            if (shouldFillUserFields()) {
                Long currentUserId = getCurrentUserId();
                this.strictInsertFill(metaObject, "createBy", String.class, String.valueOf(currentUserId));
                this.strictInsertFill(metaObject, "updateBy", String.class, String.valueOf(currentUserId));
                log.debug("自动填充插入字段 - 用户ID: {}, 时间: {}", currentUserId, now);
            } else {
                log.debug("跳过用户字段自动填充 - 排除路径或非Web环境");
            }
        } catch (Exception e) {
            log.error("自动填充插入字段时发生异常", e);
        }
    }

    /**
     * 更新时自动填充
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        try {
            Date now = new Date();
            
            // 更新时间始终自动填充（所有环境都需要）
            this.strictUpdateFill(metaObject, "updateTime", Date.class, now);
            
            // 用户字段根据环境和路径判断是否填充
            if (shouldFillUserFields()) {
                Long currentUserId = getCurrentUserId();
                this.strictUpdateFill(metaObject, "updateBy", String.class, String.valueOf(currentUserId));
                log.debug("自动填充更新字段 - 用户ID: {}, 时间: {}", currentUserId, now);
            } else {
                log.debug("跳过用户字段自动填充 - 排除路径或非Web环境");
            }
        } catch (Exception e) {
            log.error("自动填充更新字段时发生异常", e);
        }
    }

    /**
     * 判断是否应该填充用户字段
     * 
     * @return true-需要填充，false-不需要填充
     */
    private boolean shouldFillUserFields() {
        // 非Web环境（如定时任务、消息队列）不填充用户字段
        if (!isWebEnvironment()) {
            return false;
        }
        
        // 排除特定路径（如小程序端接口）
        if (isExcludePath()) {
            return false;
        }
        
        return true;
    }

    /**
     * 判断是否为Web环境
     * 
     * @return true-Web环境，false-非Web环境
     */
    private boolean isWebEnvironment() {
        try {
            return RequestContextHolder.getRequestAttributes() != null;
        } catch (IllegalStateException e) {
            return false;
        }
    }

    /**
     * 判断当前请求路径是否在排除列表中
     * 
     * @return true-需要排除，false-不需要排除
     */
    private boolean isExcludePath() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) 
                    RequestContextHolder.getRequestAttributes();
            
            if (attributes == null) {
                return false;
            }
            
            HttpServletRequest request = attributes.getRequest();
            String requestURI = request.getRequestURI();
            
            return requestURI.startsWith(EXCLUDE_PATH_PREFIX);
        } catch (Exception e) {
            log.warn("判断排除路径时发生异常", e);
            // 异常时为了安全起见，选择排除
            return true;
        }
    }

    /**
     * 获取当前登录用户ID
     * 
     * @return 用户ID，获取失败时返回默认值
     */
    private Long getCurrentUserId() {
        try {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            if (Objects.nonNull(loginUser) && Objects.nonNull(loginUser.getUserId())) {
                return loginUser.getUserId();
            }
        } catch (Exception e) {
            log.debug("获取当前登录用户ID失败，使用默认值", e);
        }
        return DEFAULT_USER_ID;
    }
}
